﻿/*
   Copyright 2011 Softisis

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System;
using FOM.Interfaces;

namespace FOM.Impl
{
    /// <summary>
    /// This class represents a flattened view of the mapping. This is internally used by the mapping engine
    /// and should not be instancied for something else.
    /// </summary>
    /// <remarks>Copyright Softisis 11/2011 (France)</remarks>
    internal class FlatMappingDescriptor : IComparable<FlatMappingDescriptor>
    {
        /// <summary>
        /// Original node from which this flat mapping comes from.
        /// </summary>
        internal AbstractMappingNode SourceNode { get; private set; }

        /// <summary>
        /// Full path links (i.e. from the root element, dot separated).
        /// </summary>
        internal IPathLink FullPathLink { get; set; }


        private static long _declarationId=0;
        internal static long AutoDeclarationId
        {
            get { return _declarationId++; }
        }

        internal long Id { get; private set; }


        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="src">Original node from which this flat mapping build from.</param>
        /// <param name="fullsrcpath">Full source path poiting at the value to retrieve</param>
        /// <param name="fulltgtpath">Full target path pointing at the value to set.</param>
        internal FlatMappingDescriptor(AbstractMappingNode src, 
            String fullsrcpath,
            String fulltgtpath)
        {
            SourceNode = src;
            FullPathLink = new PathLink(fullsrcpath, fulltgtpath);
            Id = AutoDeclarationId;
        }

        /// <summary>
        /// Comparison is done for target path, because this is the key of the mapping. (In effect, source
        /// can be used to target multiple fields).
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public int CompareTo(FlatMappingDescriptor other)
        {
            var ret= FullPathLink.TargetPath.CompareTo(other.FullPathLink.TargetPath);
            if (ret == 0)
                return Id.CompareTo(other.Id);
            return ret;
        }

        public override bool Equals(object obj)
        {
            return Equals(obj as FlatMappingDescriptor);
        }


        public bool Equals(FlatMappingDescriptor other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            var eq= Equals(other.FullPathLink.TargetPath, FullPathLink.TargetPath);
            if (eq)
                return Id.Equals(other.Id);

            return false;
        }

        public override int GetHashCode()
        {
            return (int) ((FullPathLink.TargetPath != null ? FullPathLink.TargetPath.GetHashCode() : 0) * Id);
        }
    }
}
